/*
Copyright (c) 2022 Huawei Device Co., Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

import Directory from '../../Directory'
import NikonType2MakernoteDescriptor from './NikonType2MakernoteDescriptor'
import LogUtil from '../../../tools/LogUtils'

const TAG: string = "NikonType2MakernoteDirectory";

/**
 * Describes tags specific to Nikon (type 2) cameras.  Type-2 applies to the E990 and D-series cameras such as the E990, D1,
 * D70 and D100.
 * <p>
 * Thanks to Fabrizio Giudici for publishing his reverse-engineering of the D100 makernote data.
 * <p>
 * Note that the camera implements image protection (locking images) via the file's 'readonly' attribute.  Similarly
 * image hiding uses the 'hidden' attribute (observed on the D70).  Consequently, these values are not available here.
 * <p>
 * Additional sample images have been observed, and their tag values recorded in javadoc comments for each tag's field.
 * New tags have subsequently been added since Fabrizio's observations.
 * <p>
 * In earlier models (such as the E990 and D1), this directory begins at the first byte of the makernote IFD.  In
 * later models, the IFD was given the standard prefix to indicate the camera models (most other manufacturers also
 * provide this prefix to aid in software decoding).
 *
 */

class NikonType2MakernoteDirectory extends Directory {
  /**
   * Values observed
   * - 0200 (D70)
   * - 0200 (D1X)
   */
  public static TAG_FIRMWARE_VERSION = 0x0001;

  /**
   * Values observed
   * - 0 250
   * - 0 400
   */
  public static TAG_ISO_1 = 0x0002;

  /**
   * The camera's color mode, as an uppercase string.  Examples include:
   * <ul>
   * <li><code>B &amp; W</code></li>
   * <li><code>COLOR</code></li>
   * <li><code>COOL</code></li>
   * <li><code>SEPIA</code></li>
   * <li><code>VIVID</code></li>
   * </ul>
   */
  public static TAG_COLOR_MODE = 0x0003;

  /**
   * The camera's quality setting, as an uppercase string.  Examples include:
   * <ul>
   * <li><code>BASIC</code></li>
   * <li><code>FINE</code></li>
   * <li><code>NORMAL</code></li>
   * <li><code>RAW</code></li>
   * <li><code>RAW2.7M</code></li>
   * </ul>
   */
  public static TAG_QUALITY_AND_FILE_FORMAT = 0x0004;

  /**
   * The camera's white balance setting, as an uppercase string.  Examples include:
   *
   * <ul>
   * <li><code>AUTO</code></li>
   * <li><code>CLOUDY</code></li>
   * <li><code>FLASH</code></li>
   * <li><code>FLUORESCENT</code></li>
   * <li><code>INCANDESCENT</code></li>
   * <li><code>PRESET</code></li>
   * <li><code>PRESET0</code></li>
   * <li><code>PRESET1</code></li>
   * <li><code>PRESET3</code></li>
   * <li><code>SUNNY</code></li>
   * <li><code>WHITE PRESET</code></li>
   * <li><code>4350K</code></li>
   * <li><code>5000K</code></li>
   * <li><code>DAY WHITE FL</code></li>
   * <li><code>SHADE</code></li>
   * </ul>
   */
  public static TAG_CAMERA_WHITE_BALANCE  = 0x0005;

  /**
   * The camera's sharpening setting, as an uppercase string.  Examples include:
   *
   * <ul>
   * <li><code>AUTO</code></li>
   * <li><code>HIGH</code></li>
   * <li><code>LOW</code></li>
   * <li><code>NONE</code></li>
   * <li><code>NORMAL</code></li>
   * <li><code>MED.H</code></li>
   * <li><code>MED.L</code></li>
   * </ul>
   */
  public static TAG_CAMERA_SHARPENING = 0x0006;

  /**
   * The camera's auto-focus mode, as an uppercase string.  Examples include:
   *
   * <ul>
   * <li><code>AF-C</code></li>
   * <li><code>AF-S</code></li>
   * <li><code>MANUAL</code></li>
   * <li><code>AF-A</code></li>
   * </ul>
   */
  public static TAG_AF_TYPE = 0x0007;

  /**
   * The camera's flash setting, as an uppercase string.  Examples include:
   *
   * <ul>
   * <li><code></code></li>
   * <li><code>NORMAL</code></li>
   * <li><code>RED-EYE</code></li>
   * <li><code>SLOW</code></li>
   * <li><code>NEW_TTL</code></li>
   * <li><code>REAR</code></li>
   * <li><code>REAR SLOW</code></li>
   * </ul>
   * Note: when TAG_AUTO_FLASH_MODE is blank (whitespace), Nikon Browser displays "Flash Sync Mode: Not Attached"
   */
  public static TAG_FLASH_SYNC_MODE = 0x0008;

  /**
   * The type of flash used in the photograph, as a string.  Examples include:
   *
   * <ul>
   * <li><code></code></li>
   * <li><code>Built-in,TTL</code></li>
   * <li><code>NEW_TTL</code> Nikon Browser interprets as "D-TTL"</li>
   * <li><code>Built-in,M</code></li>
   * <li><code>Optional,TTL</code> with speedlight SB800, flash sync mode as "NORMAL"</li>
   * </ul>
   */
  public static TAG_AUTO_FLASH_MODE = 0x0009;

  /**
   * An unknown tag, as a rational.  Several values given here:
   */
  public static TAG_UNKNOWN_34 = 0x000A;

  /**
   * The camera's white balance bias setting, as an uint16 array having either one or two elements.
   *
   * <ul>
   * <li><code>0</code></li>
   * <li><code>1</code></li>
   * <li><code>-3</code></li>
   * <li><code>-2</code></li>
   * <li><code>-1</code></li>
   * <li><code>0,0</code></li>
   * <li><code>1,0</code></li>
   * <li><code>5,-5</code></li>
   * </ul>
   */
  public static TAG_CAMERA_WHITE_BALANCE_FINE = 0x000B;

  /**
   * The first two numbers are coefficients to multiply red and blue channels according to white balance as set in the
   * camera. The meaning of the third and the fourth numbers is unknown.
   *
   * Values observed
   * - 2.25882352 1.76078431 0.0 0.0
   * - 10242/1 34305/1 0/1 0/1
   * - 234765625/100000000 1140625/1000000 1/1 1/1
   */
  public static TAG_CAMERA_WHITE_BALANCE_RB_COEFF = 0x000C;

  /**
   * The camera's program shift setting, as an array of four integers.
   * The value, in EV, is calculated as <code>a*b/c</code>.
   *
   * <ul>
   * <li><code>0,1,3,0</code> = 0 EV</li>
   * <li><code>1,1,3,0</code> = 0.33 EV</li>
   * <li><code>-3,1,3,0</code> = -1 EV</li>
   * <li><code>1,1,2,0</code> = 0.5 EV</li>
   * <li><code>2,1,6,0</code> = 0.33 EV</li>
   * </ul>
   */
  public static TAG_PROGRAM_SHIFT = 0x000D;

  /**
   * The exposure difference, as an array of four integers.
   * The value, in EV, is calculated as <code>a*b/c</code>.
   *
   * <ul>
   * <li><code>-105,1,12,0</code> = -8.75 EV</li>
   * <li><code>-72,1,12,0</code> = -6.00 EV</li>
   * <li><code>-11,1,12,0</code> = -0.92 EV</li>
   * </ul>
   */
  public static TAG_EXPOSURE_DIFFERENCE = 0x000E;

  /**
   * The camera's ISO mode, as an uppercase string.
   *
   * <ul>
   * <li><code>AUTO</code></li>
   * <li><code>MANUAL</code></li>
   * </ul>
   */
  public static TAG_ISO_MODE = 0x000F;

  /**
   * Added during merge of Type2 &amp; Type3.  May apply to earlier models, such as E990 and D1.
   */
  public static TAG_DATA_DUMP = 0x0010;

  /**
   * Preview to another IFD (?)
   * <p>
   */
  public static TAG_PREVIEW_IFD = 0x0011;

  /**
   * The flash compensation, as an array of four integers.
   * The value, in EV, is calculated as <code>a*b/c</code>.
   *
   * <ul>
   * <li><code>-18,1,6,0</code> = -3 EV</li>
   * <li><code>4,1,6,0</code> = 0.67 EV</li>
   * <li><code>6,1,6,0</code> = 1 EV</li>
   * </ul>
   */
  public static TAG_AUTO_FLASH_COMPENSATION = 0x0012;

  /**
   * The requested ISO value, as an array of two integers.
   *
   * <ul>
   * <li><code>0,0</code></li>
   * <li><code>0,125</code></li>
   * <li><code>1,2500</code></li>
   * </ul>
   */
  public static TAG_ISO_REQUESTED = 0x0013;

  /**
   * Defines the photo corner coordinates, in 8 bytes.  Treated as four 16-bit integers, they
   * decode as: top-left (x,y); bot-right (x,y)
   * - 0 0 49163 53255
   * - 0 0 3008 2000 (the image dimensions were 3008x2000) (D70)
   * <ul>
   * <li><code>0,0,4288,2848</code> The max resolution of the D300 camera</li>
   * <li><code>0,0,3008,2000</code> The max resolution of the D70 camera</li>
   * <li><code>0,0,4256,2832</code> The max resolution of the D3 camera</li>
   * </ul>
   */
  public static TAG_IMAGE_BOUNDARY = 0x0016;

  /**
   * The flash exposure compensation, as an array of four integers.
   * The value, in EV, is calculated as <code>a*b/c</code>.
   *
   * <ul>
   * <li><code>0,0,0,0</code> = 0 EV</li>
   * <li><code>0,1,6,0</code> = 0 EV</li>
   * <li><code>4,1,6,0</code> = 0.67 EV</li>
   * </ul>
   */
  public static TAG_FLASH_EXPOSURE_COMPENSATION = 0x0017;

  /**
   * The flash bracket compensation, as an array of four integers.
   * The value, in EV, is calculated as <code>a*b/c</code>.
   *
   * <ul>
   * <li><code>0,0,0,0</code> = 0 EV</li>
   * <li><code>0,1,6,0</code> = 0 EV</li>
   * <li><code>4,1,6,0</code> = 0.67 EV</li>
   * </ul>
   */
  public static TAG_FLASH_BRACKET_COMPENSATION = 0x0018;

    /**
     * The AE bracket compensation, as a rational number.
     *
     * <ul>
     * <li><code>0/0</code></li>
     * <li><code>0/1</code></li>
     * <li><code>0/6</code></li>
     * <li><code>4/6</code></li>
     * <li><code>6/6</code></li>
     * </ul>
     */
  public static TAG_AE_BRACKET_COMPENSATION = 0x0019;

  /**
   * Flash mode, as a string.
   *
   * <ul>
   * <li><code></code></li>
   * <li><code>Red Eye Reduction</code></li>
   * <li><code>D-Lighting</code></li>
   * <li><code>Distortion control</code></li>
   * </ul>
   */
  public static TAG_FLASH_MODE = 0x001a;

  public static TAG_CROP_HIGH_SPEED = 0x001b;
  public static TAG_EXPOSURE_TUNING = 0x001c;

  /**
   * The camera's serial number, as a string.
   * Note that D200 is always blank, and D50 is always <code>"D50"</code>.
   */
  public static TAG_CAMERA_SERIAL_NUMBER = 0x001d;

  /**
   * The camera's color space setting.
   *
   * <ul>
   * <li><code>1</code> sRGB</li>
   * <li><code>2</code> Adobe RGB</li>
   * </ul>
   */
  public static TAG_COLOR_SPACE = 0x001e;
  public static TAG_VR_INFO = 0x001f;
  public static TAG_IMAGE_AUTHENTICATION = 0x0020;
  public static TAG_UNKNOWN_35 = 0x0021;

  /**
   * The active D-Lighting setting.
   *
   * <ul>
   * <li><code>0</code> Off</li>
   * <li><code>1</code> Low</li>
   * <li><code>3</code> Normal</li>
   * <li><code>5</code> High</li>
   * <li><code>7</code> Extra High</li>
   * <li><code>65535</code> Auto</li>
   * </ul>
   */
  public static TAG_ACTIVE_D_LIGHTING = 0x0022;
  public static TAG_PICTURE_CONTROL = 0x0023;
  public static TAG_WORLD_TIME = 0x0024;
  public static TAG_ISO_INFO = 0x0025;
  public static TAG_UNKNOWN_36 = 0x0026;
  public static TAG_UNKNOWN_37 = 0x0027;
  public static TAG_UNKNOWN_38 = 0x0028;
  public static TAG_UNKNOWN_39 = 0x0029;

  /**
   * The camera's vignette control setting.
   *
   * <ul>
   * <li><code>0</code> Off</li>
   * <li><code>1</code> Low</li>
   * <li><code>3</code> Normal</li>
   * <li><code>5</code> High</li>
   * </ul>
   */
  public static TAG_VIGNETTE_CONTROL = 0x002a;
  public static TAG_UNKNOWN_40 = 0x002b;
  public static TAG_UNKNOWN_41 = 0x002c;
  public static TAG_UNKNOWN_42 = 0x002d;
  public static TAG_UNKNOWN_43 = 0x002e;
  public static TAG_UNKNOWN_44 = 0x002f;
  public static TAG_UNKNOWN_45 = 0x0030;
  public static TAG_UNKNOWN_46 = 0x0031;

  /**
   * The camera's image adjustment setting, as a string.
   *
   * <ul>
   * <li><code>AUTO</code></li>
   * <li><code>CONTRAST(+)</code></li>
   * <li><code>CONTRAST(-)</code></li>
   * <li><code>NORMAL</code></li>
   * <li><code>B &amp; W</code></li>
   * <li><code>BRIGHTNESS(+)</code></li>
   * <li><code>BRIGHTNESS(-)</code></li>
   * <li><code>SEPIA</code></li>
   * </ul>
   */
  public static TAG_IMAGE_ADJUSTMENT = 0x0080;

  /**
   * The camera's tone compensation setting, as a string.
   *
   * <ul>
   * <li><code>NORMAL</code></li>
   * <li><code>LOW</code></li>
   * <li><code>MED.L</code></li>
   * <li><code>MED.H</code></li>
   * <li><code>HIGH</code></li>
   * <li><code>AUTO</code></li>
   * </ul>
   */
  public static TAG_CAMERA_TONE_COMPENSATION = 0x0081;

  /**
   * A description of any auxiliary lens, as a string.
   *
   * <ul>
   * <li><code>OFF</code></li>
   * <li><code>FISHEYE 1</code></li>
   * <li><code>FISHEYE 2</code></li>
   * <li><code>TELEPHOTO 2</code></li>
   * <li><code>WIDE ADAPTER</code></li>
   * </ul>
   */
  public static TAG_ADAPTER = 0x0082;

  /**
   * The type of lens used, as a byte.
   *
   * <ul>
   * <li><code>0x00</code> AF</li>
   * <li><code>0x01</code> MF</li>
   * <li><code>0x02</code> D</li>
   * <li><code>0x06</code> G, D</li>
   * <li><code>0x08</code> VR</li>
   * <li><code>0x0a</code> VR, D</li>
   * <li><code>0x0e</code> VR, G, D</li>
   * </ul>
   */
  public static TAG_LENS_TYPE = 0x0083;

  /**
   * A pair of focal/max-fstop values that describe the lens used.
   *
   * Values observed
   * - 180.0,180.0,2.8,2.8 (D100)
   * - 240/10 850/10 35/10 45/10
   * - 18-70mm f/3.5-4.5 (D70)
   * - 17-35mm f/2.8-2.8 (D1X)
   * - 70-200mm f/2.8-2.8 (D70)
   *
   * Nikon Browser identifies the lens as "18-70mm F/3.5-4.5 G" which
   * is identical to metadata extractor, except for the "G".  This must
   * be coming from another tag...
   */
  public static TAG_LENS = 0x0084;

  /**
   * Added during merge of Type2 &amp; Type3.  May apply to earlier models, such as E990 and D1.
   */
  public static TAG_MANUAL_FOCUS_DISTANCE = 0x0085;

  /**
   * The amount of digital zoom used.
   */
  public static TAG_DIGITAL_ZOOM = 0x0086;

  /**
   * Whether the flash was used in this image.
   *
   * <ul>
   * <li><code>0</code> Flash Not Used</li>
   * <li><code>1</code> Manual Flash</li>
   * <li><code>3</code> Flash Not Ready</li>
   * <li><code>7</code> External Flash</li>
   * <li><code>8</code> Fired, Commander Mode</li>
   * <li><code>9</code> Fired, TTL Mode</li>
   * </ul>
   */
  public static TAG_FLASH_USED = 0x0087;

  /**
   * The position of the autofocus target.
   */
  public static TAG_AF_FOCUS_POSITION = 0x0088;

  /**
   * The camera's shooting mode.
   * <p>
   * A bit-array with:
   * <ul>
   * <li><code>0</code> Single Frame</li>
   * <li><code>1</code> Continuous</li>
   * <li><code>2</code> Delay</li>
   * <li><code>8</code> PC Control</li>
   * <li><code>16</code> Exposure Bracketing</li>
   * <li><code>32</code> Auto ISO</li>
   * <li><code>64</code> White-Balance Bracketing</li>
   * <li><code>128</code> IR Control</li>
   * </ul>
   */
  public static TAG_SHOOTING_MODE = 0x0089;

  public static TAG_UNKNOWN_20 = 0x008A;

  /**
   * Lens stops, as an array of four integers.
   * The value, in EV, is calculated as <code>a*b/c</code>.
   *
   * <ul>
   * <li><code>64,1,12,0</code> = 5.33 EV</li>
   * <li><code>72,1,12,0</code> = 6 EV</li>
   * </ul>
   */
  public static TAG_LENS_STOPS = 0x008B;

  public static TAG_CONTRAST_CURVE = 0x008C;

  /**
   * The color space as set in the camera, as a string.
   *
   * <ul>
   * <li><code>MODE1</code> = Mode 1 (sRGB)</li>
   * <li><code>MODE1a</code> = Mode 1 (sRGB)</li>
   * <li><code>MODE2</code> = Mode 2 (Adobe RGB)</li>
   * <li><code>MODE3</code> = Mode 2 (sRGB): Higher Saturation</li>
   * <li><code>MODE3a</code> = Mode 2 (sRGB): Higher Saturation</li>
   * <li><code>B &amp; W</code> = B &amp; W</li>
   * </ul>
   */
  public static TAG_CAMERA_COLOR_MODE = 0x008D;
  public static TAG_UNKNOWN_47 = 0x008E;

  /**
   * The camera's scene mode, as a string.  Examples include:
   * <ul>
   * <li><code>BEACH/SNOW</code></li>
   * <li><code>CLOSE UP</code></li>
   * <li><code>NIGHT PORTRAIT</code></li>
   * <li><code>PORTRAIT</code></li>
   * <li><code>ANTI-SHAKE</code></li>
   * <li><code>BACK LIGHT</code></li>
   * <li><code>BEST FACE</code></li>
   * <li><code>BEST</code></li>
   * <li><code>COPY</code></li>
   * <li><code>DAWN/DUSK</code></li>
   * <li><code>FACE-PRIORITY</code></li>
   * <li><code>FIREWORKS</code></li>
   * <li><code>FOOD</code></li>
   * <li><code>HIGH SENS.</code></li>
   * <li><code>LAND SCAPE</code></li>
   * <li><code>MUSEUM</code></li>
   * <li><code>PANORAMA ASSIST</code></li>
   * <li><code>PARTY/INDOOR</code></li>
   * <li><code>SCENE AUTO</code></li>
   * <li><code>SMILE</code></li>
   * <li><code>SPORT</code></li>
   * <li><code>SPORT CONT.</code></li>
   * <li><code>SUNSET</code></li>
   * </ul>
   */
  public static TAG_SCENE_MODE = 0x008F;

  /**
   * The lighting type, as a string.  Examples include:
   * <ul>
   * <li><code></code></li>
   * <li><code>NATURAL</code></li>
   * <li><code>SPEEDLIGHT</code></li>
   * <li><code>COLORED</code></li>
   * <li><code>MIXED</code></li>
   * <li><code>NORMAL</code></li>
   * </ul>
   */
  public static TAG_LIGHT_SOURCE = 0x0090;

  /**
   * Advertised as ASCII, but actually isn't.  A variable number of bytes (eg. 18 to 533).  Actual number of bytes
   * appears fixed for a given camera model.
   */
  public static TAG_SHOT_INFO = 0x0091;

  /**
   * The hue adjustment as set in the camera.  Values observed are either 0 or 3.
   */
  public static TAG_CAMERA_HUE_ADJUSTMENT = 0x0092;
  /**
   * The NEF (RAW) compression.  Examples include:
   * <ul>
   * <li><code>1</code> Lossy (Type 1)</li>
   * <li><code>2</code> Uncompressed</li>
   * <li><code>3</code> Lossless</li>
   * <li><code>4</code> Lossy (Type 2)</li>
   * </ul>
   */
  public static TAG_NEF_COMPRESSION = 0x0093;

  /**
   * The saturation level, as a signed integer.  Examples include:
   * <ul>
   * <li><code>+3</code></li>
   * <li><code>+2</code></li>
   * <li><code>+1</code></li>
   * <li><code>0</code> Normal</li>
   * <li><code>-1</code></li>
   * <li><code>-2</code></li>
   * <li><code>-3</code> (B&amp;W)</li>
   * </ul>
   */
  public static TAG_SATURATION = 0x0094;

  /**
   * The type of noise reduction, as a string.  Examples include:
   * <ul>
   * <li><code>OFF</code></li>
   * <li><code>FPNR</code></li>
   * </ul>
   */
  public static TAG_NOISE_REDUCTION = 0x0095;
  public static TAG_LINEARIZATION_TABLE = 0x0096;
  public static TAG_COLOR_BALANCE = 0x0097;
  public static TAG_LENS_DATA = 0x0098;

  /** The NEF (RAW) thumbnail size, as an integer array with two items representing [width,height]. */
  public static TAG_NEF_THUMBNAIL_SIZE = 0x0099;

  /** The sensor pixel size, as a pair of rational numbers. */
  public static TAG_SENSOR_PIXEL_SIZE = 0x009A;
  public static TAG_UNKNOWN_10 = 0x009B;
  public static TAG_SCENE_ASSIST = 0x009C;
  public static TAG_UNKNOWN_11 = 0x009D;
  public static TAG_RETOUCH_HISTORY = 0x009E;
  public static TAG_UNKNOWN_12 = 0x009F;

  /**
   * The camera serial number, as a string.
   * <ul>
   * <li><code>NO= 00002539</code></li>
   * <li><code>NO= -1000d71</code></li>
   * <li><code>PKG597230621263</code></li>
   * <li><code>PKG5995671330625116</code></li>
   * <li><code>PKG49981281631130677</code></li>
   * <li><code>BU672230725063</code></li>
   * <li><code>NO= 200332c7</code></li>
   * <li><code>NO= 30045efe</code></li>
   * </ul>
   */
  public static TAG_CAMERA_SERIAL_NUMBER_2 = 0x00A0;

  public static TAG_IMAGE_DATA_SIZE = 0x00A2;

  public static TAG_UNKNOWN_27 = 0x00A3;
  public static TAG_UNKNOWN_28 = 0x00A4;
  public static TAG_IMAGE_COUNT = 0x00A5;
  public static TAG_DELETED_IMAGE_COUNT = 0x00A6;

  /** The number of total shutter releases.  This value increments for each exposure (observed on D70). */
  public static TAG_EXPOSURE_SEQUENCE_NUMBER = 0x00A7;

  public static TAG_FLASH_INFO = 0x00A8;
  /**
   * The camera's image optimisation, as a string.
   * <ul>
   *     <li><code></code></li>
   *     <li><code>NORMAL</code></li>
   *     <li><code>CUSTOM</code></li>
   *     <li><code>BLACK AND WHITE</code></li>
   *     <li><code>LAND SCAPE</code></li>
   *     <li><code>MORE VIVID</code></li>
   *     <li><code>PORTRAIT</code></li>
   *     <li><code>SOFT</code></li>
   *     <li><code>VIVID</code></li>
   * </ul>
   */
  public static TAG_IMAGE_OPTIMISATION = 0x00A9;

  /**
   * The camera's saturation level, as a string.
   * <ul>
   *     <li><code></code></li>
   *     <li><code>NORMAL</code></li>
   *     <li><code>AUTO</code></li>
   *     <li><code>ENHANCED</code></li>
   *     <li><code>MODERATE</code></li>
   * </ul>
   */
  public static TAG_SATURATION_2 = 0x00AA;

  /**
   * The camera's digital vari-program setting, as a string.
   * <ul>
   *     <li><code></code></li>
   *     <li><code>AUTO</code></li>
   *     <li><code>AUTO(FLASH OFF)</code></li>
   *     <li><code>CLOSE UP</code></li>
   *     <li><code>LANDSCAPE</code></li>
   *     <li><code>NIGHT PORTRAIT</code></li>
   *     <li><code>PORTRAIT</code></li>
   *     <li><code>SPORT</code></li>
   * </ul>
   */
  public static TAG_DIGITAL_VARI_PROGRAM = 0x00AB;

  /**
   * The camera's digital vari-program setting, as a string.
   * <ul>
   *     <li><code></code></li>
   *     <li><code>VR-ON</code></li>
   *     <li><code>VR-OFF</code></li>
   *     <li><code>VR-HYBRID</code></li>
   *     <li><code>VR-ACTIVE</code></li>
   * </ul>
   */
  public static TAG_IMAGE_STABILISATION = 0x00AC;

  /**
   * The camera's digital vari-program setting, as a string.
   * <ul>
   *     <li><code></code></li>
   *     <li><code>HYBRID</code></li>
   *     <li><code>STANDARD</code></li>
   * </ul>
   */
  public static TAG_AF_RESPONSE = 0x00AD;
  public static TAG_UNKNOWN_29 = 0x00AE;
  public static TAG_UNKNOWN_30 = 0x00AF;
  public static TAG_MULTI_EXPOSURE = 0x00B0;

  /**
   * The camera's high ISO noise reduction setting, as an integer.
   * <ul>
   *     <li><code>0</code> Off</li>
   *     <li><code>1</code> Minimal</li>
   *     <li><code>2</code> Low</li>
   *     <li><code>4</code> Normal</li>
   *     <li><code>6</code> High</li>
   * </ul>
   */
  public static TAG_HIGH_ISO_NOISE_REDUCTION = 0x00B1;
  public static TAG_UNKNOWN_31 = 0x00B2;
  public static TAG_UNKNOWN_32 = 0x00B3;
  public static TAG_UNKNOWN_33 = 0x00B4;
  public static TAG_UNKNOWN_48 = 0x00B5;
  public static TAG_POWER_UP_TIME = 0x00B6;
  public static TAG_AF_INFO_2 = 0x00B7;
  public static TAG_FILE_INFO = 0x00B8;
  public static TAG_AF_TUNE = 0x00B9;
  public static TAG_UNKNOWN_49 = 0x00BB;
  public static TAG_UNKNOWN_50 = 0x00BD;
  public static TAG_UNKNOWN_51 = 0x0103;
  public static TAG_PRINT_IMAGE_MATCHING_INFO = 0x0E00;

  /**
   * Data about changes set by Nikon Capture Editor.
   *
   * Values observed
   */
  public static TAG_NIKON_CAPTURE_DATA = 0x0E01;
  public static TAG_UNKNOWN_52 = 0x0E05;
  public static TAG_UNKNOWN_53 = 0x0E08;
  public static TAG_NIKON_CAPTURE_VERSION = 0x0E09;
  public static TAG_NIKON_CAPTURE_OFFSETS = 0x0E0E;
  public static TAG_NIKON_SCAN = 0x0E10;
  public static TAG_UNKNOWN_54 = 0x0E19;
  public static TAG_NEF_BIT_DEPTH = 0x0E22;
  public static TAG_UNKNOWN_55 = 0x0E23;

  public static _tagNameMap: Map<number, string> = new Map([
    [NikonType2MakernoteDirectory.TAG_FIRMWARE_VERSION, "Firmware Version"],
    [NikonType2MakernoteDirectory.TAG_ISO_1, "ISO"],
    [NikonType2MakernoteDirectory.TAG_QUALITY_AND_FILE_FORMAT, "Quality & File Format"],
    [NikonType2MakernoteDirectory.TAG_CAMERA_WHITE_BALANCE, "White Balance"],
    [NikonType2MakernoteDirectory.TAG_CAMERA_SHARPENING, "Sharpening"],
    [NikonType2MakernoteDirectory.TAG_AF_TYPE, "AF Type"],
    [NikonType2MakernoteDirectory.TAG_CAMERA_WHITE_BALANCE_FINE, "White Balance Fine"],
    [NikonType2MakernoteDirectory.TAG_CAMERA_WHITE_BALANCE_RB_COEFF, "White Balance RB Coefficients"],
    [NikonType2MakernoteDirectory.TAG_ISO_REQUESTED, "ISO"],
    [NikonType2MakernoteDirectory.TAG_ISO_MODE, "ISO Mode"],
    [NikonType2MakernoteDirectory.TAG_DATA_DUMP, "Data Dump"],

    [NikonType2MakernoteDirectory.TAG_PROGRAM_SHIFT, "Program Shift"],
    [NikonType2MakernoteDirectory.TAG_EXPOSURE_DIFFERENCE, "Exposure Difference"],
    [NikonType2MakernoteDirectory.TAG_PREVIEW_IFD, "Preview IFD"],
    [NikonType2MakernoteDirectory.TAG_LENS_TYPE, "Lens Type"],
    [NikonType2MakernoteDirectory.TAG_FLASH_USED, "Flash Used"],
    [NikonType2MakernoteDirectory.TAG_AF_FOCUS_POSITION, "AF Focus Position"],
    [NikonType2MakernoteDirectory.TAG_SHOOTING_MODE, "Shooting Mode"],
    [NikonType2MakernoteDirectory.TAG_LENS_STOPS, "Lens Stops"],
    [NikonType2MakernoteDirectory.TAG_CONTRAST_CURVE, "Contrast Curve"],
    [NikonType2MakernoteDirectory.TAG_LIGHT_SOURCE, "Light source"],
    [NikonType2MakernoteDirectory.TAG_SHOT_INFO, "Shot Info"],
    [NikonType2MakernoteDirectory.TAG_COLOR_BALANCE, "Color Balance"],
    [NikonType2MakernoteDirectory.TAG_LENS_DATA, "Lens Data"],
    [NikonType2MakernoteDirectory.TAG_NEF_THUMBNAIL_SIZE, "NEF Thumbnail Size"],
    [NikonType2MakernoteDirectory.TAG_SENSOR_PIXEL_SIZE, "Sensor Pixel Size"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_10, "Unknown 10"],
    [NikonType2MakernoteDirectory.TAG_SCENE_ASSIST, "Scene Assist"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_11, "Unknown 11"],
    [NikonType2MakernoteDirectory.TAG_RETOUCH_HISTORY, "Retouch History"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_12, "Unknown 12"],
    [NikonType2MakernoteDirectory.TAG_FLASH_SYNC_MODE, "Flash Sync Mode"],
    [NikonType2MakernoteDirectory.TAG_AUTO_FLASH_MODE, "Auto Flash Mode"],
    [NikonType2MakernoteDirectory.TAG_AUTO_FLASH_COMPENSATION, "Auto Flash Compensation"],
    [NikonType2MakernoteDirectory.TAG_EXPOSURE_SEQUENCE_NUMBER, "Exposure Sequence Number"],
    [NikonType2MakernoteDirectory.TAG_COLOR_MODE, "Color Mode"],

    [NikonType2MakernoteDirectory.TAG_UNKNOWN_20, "Unknown 20"],
    [NikonType2MakernoteDirectory.TAG_IMAGE_BOUNDARY, "Image Boundary"],
    [NikonType2MakernoteDirectory.TAG_FLASH_EXPOSURE_COMPENSATION, "Flash Exposure Compensation"],
    [NikonType2MakernoteDirectory.TAG_FLASH_BRACKET_COMPENSATION, "Flash Bracket Compensation"],
    [NikonType2MakernoteDirectory.TAG_AE_BRACKET_COMPENSATION, "AE Bracket Compensation"],
    [NikonType2MakernoteDirectory.TAG_FLASH_MODE, "Flash Mode"],
    [NikonType2MakernoteDirectory.TAG_CROP_HIGH_SPEED, "Crop High Speed"],
    [NikonType2MakernoteDirectory.TAG_EXPOSURE_TUNING, "Exposure Tuning"],
    [NikonType2MakernoteDirectory.TAG_CAMERA_SERIAL_NUMBER, "Camera Serial Number"],
    [NikonType2MakernoteDirectory.TAG_COLOR_SPACE, "Color Space"],
    [NikonType2MakernoteDirectory.TAG_VR_INFO, "VR Info"],
    [NikonType2MakernoteDirectory.TAG_IMAGE_AUTHENTICATION, "Image Authentication"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_35, "Unknown 35"],
    [NikonType2MakernoteDirectory.TAG_ACTIVE_D_LIGHTING, "Active D-Lighting"],
    [NikonType2MakernoteDirectory.TAG_PICTURE_CONTROL, "Picture Control"],
    [NikonType2MakernoteDirectory.TAG_WORLD_TIME, "World Time"],
    [NikonType2MakernoteDirectory.TAG_ISO_INFO, "ISO Info"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_36, "Unknown 36"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_37, "Unknown 37"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_38, "Unknown 38"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_39, "Unknown 39"],
    [NikonType2MakernoteDirectory.TAG_VIGNETTE_CONTROL, "Vignette Control"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_40, "Unknown 40"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_41, "Unknown 41"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_42, "Unknown 42"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_43, "Unknown 43"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_44, "Unknown 44"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_45, "Unknown 45"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_46, "Unknown 46"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_47, "Unknown 47"],
    [NikonType2MakernoteDirectory.TAG_SCENE_MODE, "Scene Mode"],

    [NikonType2MakernoteDirectory.TAG_CAMERA_SERIAL_NUMBER_2, "Camera Serial Number"],
    [NikonType2MakernoteDirectory.TAG_IMAGE_DATA_SIZE, "Image Data Size"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_27, "Unknown 27"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_28, "Unknown 28"],
    [NikonType2MakernoteDirectory.TAG_IMAGE_COUNT, "Image Count"],
    [NikonType2MakernoteDirectory.TAG_DELETED_IMAGE_COUNT, "Deleted Image Count"],
    [NikonType2MakernoteDirectory.TAG_SATURATION_2, "Saturation"],
    [NikonType2MakernoteDirectory.TAG_DIGITAL_VARI_PROGRAM, "Digital Vari Program"],
    [NikonType2MakernoteDirectory.TAG_IMAGE_STABILISATION, "Image Stabilisation"],
    [NikonType2MakernoteDirectory.TAG_AF_RESPONSE, "AF Response"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_29, "Unknown 29"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_30, "Unknown 30"],
    [NikonType2MakernoteDirectory.TAG_MULTI_EXPOSURE, "Multi Exposure"],
    [NikonType2MakernoteDirectory.TAG_HIGH_ISO_NOISE_REDUCTION, "High ISO Noise Reduction"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_31, "Unknown 31"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_32, "Unknown 32"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_33, "Unknown 33"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_48, "Unknown 48"],
    [NikonType2MakernoteDirectory.TAG_POWER_UP_TIME, "Power Up Time"],
    [NikonType2MakernoteDirectory.TAG_AF_INFO_2, "AF Info 2"],
    [NikonType2MakernoteDirectory.TAG_FILE_INFO, "File Info"],
    [NikonType2MakernoteDirectory.TAG_AF_TUNE, "AF Tune"],
    [NikonType2MakernoteDirectory.TAG_FLASH_INFO, "Flash Info"],
    [NikonType2MakernoteDirectory.TAG_IMAGE_OPTIMISATION, "Image Optimisation"],

    [NikonType2MakernoteDirectory.TAG_IMAGE_ADJUSTMENT, "Image Adjustment"],
    [NikonType2MakernoteDirectory.TAG_CAMERA_TONE_COMPENSATION, "Tone Compensation"],
    [NikonType2MakernoteDirectory.TAG_ADAPTER, "Adapter"],
    [NikonType2MakernoteDirectory.TAG_LENS, "Lens"],
    [NikonType2MakernoteDirectory.TAG_MANUAL_FOCUS_DISTANCE, "Manual Focus Distance"],
    [NikonType2MakernoteDirectory.TAG_DIGITAL_ZOOM, "Digital Zoom"],
    [NikonType2MakernoteDirectory.TAG_CAMERA_COLOR_MODE, "Colour Mode"],
    [NikonType2MakernoteDirectory.TAG_CAMERA_HUE_ADJUSTMENT, "Camera Hue Adjustment"],
    [NikonType2MakernoteDirectory.TAG_NEF_COMPRESSION, "NEF Compression"],
    [NikonType2MakernoteDirectory.TAG_SATURATION, "Saturation"],
    [NikonType2MakernoteDirectory.TAG_NOISE_REDUCTION, "Noise Reduction"],
    [NikonType2MakernoteDirectory.TAG_LINEARIZATION_TABLE, "Linearization Table"],
    [NikonType2MakernoteDirectory.TAG_NIKON_CAPTURE_DATA, "Nikon Capture Data"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_49, "Unknown 49"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_50, "Unknown 50"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_51, "Unknown 51"],
    [NikonType2MakernoteDirectory.TAG_PRINT_IMAGE_MATCHING_INFO, "Print IM"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_52, "Unknown 52"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_53, "Unknown 53"],
    [NikonType2MakernoteDirectory.TAG_NIKON_CAPTURE_VERSION, "Nikon Capture Version"],
    [NikonType2MakernoteDirectory.TAG_NIKON_CAPTURE_OFFSETS, "Nikon Capture Offsets"],
    [NikonType2MakernoteDirectory.TAG_NIKON_SCAN, "Nikon Scan"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_54, "Unknown 54"],
    [NikonType2MakernoteDirectory.TAG_NEF_BIT_DEPTH, "NEF Bit Depth"],
    [NikonType2MakernoteDirectory.TAG_UNKNOWN_55, "Unknown 55"]
  ]);

  constructor() {
    super();
    this.setDescriptor(new NikonType2MakernoteDescriptor(this));
  }

  public getName(): string {
        return "Nikon Makernote";
  }

  protected getTagNameMap(): Map<number, string> {
    return NikonType2MakernoteDirectory._tagNameMap;
  }

	/** Nikon decryption tables used in exiftool */
  private static _decTable1: Array<number> = [ 0xc1,0xbf,0x6d,0x0d,0x59,0xc5,0x13,0x9d,0x83,0x61,0x6b,0x4f,0xc7,0x7f,0x3d,0x3d,
                                               0x53,0x59,0xe3,0xc7,0xe9,0x2f,0x95,0xa7,0x95,0x1f,0xdf,0x7f,0x2b,0x29,0xc7,0x0d,
                                               0xdf,0x07,0xef,0x71,0x89,0x3d,0x13,0x3d,0x3b,0x13,0xfb,0x0d,0x89,0xc1,0x65,0x1f,
                                               0xb3,0x0d,0x6b,0x29,0xe3,0xfb,0xef,0xa3,0x6b,0x47,0x7f,0x95,0x35,0xa7,0x47,0x4f,
                                               0xc7,0xf1,0x59,0x95,0x35,0x11,0x29,0x61,0xf1,0x3d,0xb3,0x2b,0x0d,0x43,0x89,0xc1,
                                               0x9d,0x9d,0x89,0x65,0xf1,0xe9,0xdf,0xbf,0x3d,0x7f,0x53,0x97,0xe5,0xe9,0x95,0x17,
                                               0x1d,0x3d,0x8b,0xfb,0xc7,0xe3,0x67,0xa7,0x07,0xf1,0x71,0xa7,0x53,0xb5,0x29,0x89,
                                               0xe5,0x2b,0xa7,0x17,0x29,0xe9,0x4f,0xc5,0x65,0x6d,0x6b,0xef,0x0d,0x89,0x49,0x2f,
                                               0xb3,0x43,0x53,0x65,0x1d,0x49,0xa3,0x13,0x89,0x59,0xef,0x6b,0xef,0x65,0x1d,0x0b,
                                               0x59,0x13,0xe3,0x4f,0x9d,0xb3,0x29,0x43,0x2b,0x07,0x1d,0x95,0x59,0x59,0x47,0xfb,
                                               0xe5,0xe9,0x61,0x47,0x2f,0x35,0x7f,0x17,0x7f,0xef,0x7f,0x95,0x95,0x71,0xd3,0xa3,
                                               0x0b,0x71,0xa3,0xad,0x0b,0x3b,0xb5,0xfb,0xa3,0xbf,0x4f,0x83,0x1d,0xad,0xe9,0x2f,
                                               0x71,0x65,0xa3,0xe5,0x07,0x35,0x3d,0x0d,0xb5,0xe9,0xe5,0x47,0x3b,0x9d,0xef,0x35,
                                               0xa3,0xbf,0xb3,0xdf,0x53,0xd3,0x97,0x53,0x49,0x71,0x07,0x35,0x61,0x71,0x2f,0x43,
                                               0x2f,0x11,0xdf,0x17,0x97,0xfb,0x95,0x3b,0x7f,0x6b,0xd3,0x25,0xbf,0xad,0xc7,0xc5,
                                               0xc5,0xb5,0x8b,0xef,0x2f,0xd3,0x07,0x6b,0x25,0x49,0x95,0x25,0x49,0x6d,0x71,0xc7 ];
  private static _decTable2: Array<number> = [ 0xa7,0xbc,0xc9,0xad,0x91,0xdf,0x85,0xe5,0xd4,0x78,0xd5,0x17,0x46,0x7c,0x29,0x4c,
                                               0x4d,0x03,0xe9,0x25,0x68,0x11,0x86,0xb3,0xbd,0xf7,0x6f,0x61,0x22,0xa2,0x26,0x34,
                                               0x2a,0xbe,0x1e,0x46,0x14,0x68,0x9d,0x44,0x18,0xc2,0x40,0xf4,0x7e,0x5f,0x1b,0xad,
                                               0x0b,0x94,0xb6,0x67,0xb4,0x0b,0xe1,0xea,0x95,0x9c,0x66,0xdc,0xe7,0x5d,0x6c,0x05,
                                               0xda,0xd5,0xdf,0x7a,0xef,0xf6,0xdb,0x1f,0x82,0x4c,0xc0,0x68,0x47,0xa1,0xbd,0xee,
                                               0x39,0x50,0x56,0x4a,0xdd,0xdf,0xa5,0xf8,0xc6,0xda,0xca,0x90,0xca,0x01,0x42,0x9d,
                                               0x8b,0x0c,0x73,0x43,0x75,0x05,0x94,0xde,0x24,0xb3,0x80,0x34,0xe5,0x2c,0xdc,0x9b,
                                               0x3f,0xca,0x33,0x45,0xd0,0xdb,0x5f,0xf5,0x52,0xc3,0x21,0xda,0xe2,0x22,0x72,0x6b,
                                               0x3e,0xd0,0x5b,0xa8,0x87,0x8c,0x06,0x5d,0x0f,0xdd,0x09,0x19,0x93,0xd0,0xb9,0xfc,
                                               0x8b,0x0f,0x84,0x60,0x33,0x1c,0x9b,0x45,0xf1,0xf0,0xa3,0x94,0x3a,0x12,0x77,0x33,
                                               0x4d,0x44,0x78,0x28,0x3c,0x9e,0xfd,0x65,0x57,0x16,0x94,0x6b,0xfb,0x59,0xd0,0xc8,
                                               0x22,0x36,0xdb,0xd2,0x63,0x98,0x43,0xa1,0x04,0x87,0x86,0xf7,0xa6,0x26,0xbb,0xd6,
                                               0x59,0x4d,0xbf,0x6a,0x2e,0xaa,0x2b,0xef,0xe6,0x78,0xb6,0x4e,0xe0,0x2f,0xdc,0x7c,
                                               0xbe,0x57,0x19,0x32,0x7e,0x2a,0xd0,0xb8,0xba,0x29,0x00,0x3c,0x52,0x7d,0xa8,0x49,
                                               0x3b,0x2d,0xeb,0x25,0x49,0xfa,0xa3,0xaa,0x39,0xa7,0xc5,0xa7,0x50,0x11,0x36,0xfb,
                                               0xc6,0x67,0x4a,0xf5,0xa5,0x12,0x65,0x7e,0xb0,0xdf,0xaf,0x4e,0xb3,0x61,0x7f,0x2f ];


    /** decryption algorithm adapted from exiftool */
  public getDecryptedIntArray(tagType: number): Array<number> {
    LogUtil.debug(TAG,`getDecryptedIntArray enter, tagType: ${tagType}`);
    let data = this.getIntArray(tagType);
    let serial = this.getInteger(NikonType2MakernoteDirectory.TAG_CAMERA_SERIAL_NUMBER);
    let count = this.getInteger(NikonType2MakernoteDirectory.TAG_EXPOSURE_SEQUENCE_NUMBER);

    if (data == null || serial == null || count == null) {
      LogUtil.debug(TAG, `getDecryptedIntArray end, data or serial or count is null`);
      return null;
    }

    let key = 0;
    for (let i = 0; i < 4; i++) {
      key ^= (count >> (i * 8)) & 0xff;
    }

    let ci = NikonType2MakernoteDirectory._decTable1[serial & 0xff];
    let cj = NikonType2MakernoteDirectory._decTable2[key];
    let ck = 0x60;

    for (let i = 4; i < data.length; i++) {
      cj = (cj + ci * ck) & 0xff;
      ck = (ck + 1) & 0xff;
      data[i] ^= cj;
    }

    LogUtil.debug(TAG, `getDecryptedIntArray end, data: ${data}`);
    return data;
    }
}

export default NikonType2MakernoteDirectory